var createError = require("http-errors");
var express = require("express");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
const jwt = require("jsonwebtoken");
const { expressjwt } = require("express-jwt");
// var createError = require("/www/server/nvm/versions/node/v16.18.0/lib/http-errors");
// var express = require("/www/server/nvm/versions/node/v16.18.0/lib/express");
// var cookieParser = require("/www/server/nvm/versions/node/v16.18.0/lib/cookie-parser");
// var logger = require("/www/server/nvm/versions/node/v16.18.0/lib/morgan");
// const jwt = require("/www/server/nvm/versions/node/v16.18.0/lib/jsonwebtoken");
// const { expressjwt } = require("/www/server/nvm/versions/node/v16.18.0/lib/express-jwt");
var path = require("path");
// 钥匙
var key = require("./disposition/key");
// jwt加密秘锁
var secretKey = "itheima No1 ^_^";
// 路由
var getRouter = require("./routes/get");
var indexRouter = require("./routes/index");
var increaseRouter = require("./routes/increase");
var reviseRouter = require("./routes/revise");
var auditRouter = require("./routes/audit");
var wikiRouter = require("./routes/wiki");
var DeleteRouter = require("./routes/delete");
// 钥匙
var key = require("./disposition/key");
// 引入数据库配置文件
const db = require("./disposition/db");
const { log } = require("console");
const NodeRSA = require("node-rsa");

var app = express();

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "jade");

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public/dist")));
app.use(express.static(path.join(__dirname, "public")));
// 无需验证tokey接口——————————————————————————————————————————————————————————————————————————————————
// 登录接口
app.use("/", indexRouter);
app.use("/wiki", wikiRouter);
// TODO_04：注册将 JWT 字符串解析还原成 JSON 对象的中间件
// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 req.user 属性上
app.use(
  expressjwt({ secret: secretKey, algorithms: ["HS256"] }).unless({
    path: ["/login"],
  })
);
// 登录验证————————————————————————————————————————————————————————————————————————————————————————
app.post("/login", function (req, res) {
  //  判断参数是否异常
  if (req.body.account === undefined || req.body.password === undefined) {
    res.send({
      msg: "参数错误",
      success: false,
    });
    return;
  }
  // 使用私锁进行解密密码
  const privateKey = new NodeRSA(key.privatekey);
  privateKey.setOptions({ encryptionScheme: "pkcs1" });
  const password = privateKey.decrypt(req.body.password, "utf8");
  // 查询数据库
  const sql = `SELECT * FROM user WHERE Account='${req.body.account}' and password='${password}'`;
  // 进行校验用户信息
  db.query(sql, function (err, result) {
    if (err) {
      return;
    }
    // 判断校验结果
    if (result.length === 0) {
      res.send({
        msg: "账号或密码错误！",
        success: false,
      });
    } else if (result.length !== 0 && result[0].disable === 1) {
      res.send({
        msg: "你是黑名单用户，无法登录！请联系管理员解封黑名单",
        success: false,
      });
    } else {
      // tokey生成
      const tokey = jwt.sign(
        {
          id: result[0].id,
          name: result[0].name,
          Permissions: result[0].Permissions,
          disable: result[0].disable,
        },
        secretKey,
        {
          expiresIn: "24h",
        }
      );

      res.send({
        data: {
          tokey: tokey,
          user: {
            name: result[0].name,
          },
        },
        success: true,
      });
    }
  });
});
// 全局中间组件
app.use(function (req, res, next) {
  //  字段转化tokey然后判定是否可以通过登录验证来请求其他接口
  const sql = `SELECT*from user WHERE id="${req.auth.id}"`;
  db.query(sql, function (err, rows) {
    if (rows.length === 0) {
      res.send({ msg: "未知错误", success: false });
    } else {
      // 判断是否有权限
      if (rows[0].Permissions !== null) {
        req.auth.Permissions === rows[0].Permissions
          ? next()
          : res.send({
              msg: "你的权限码与系统不一致，请联系管理员",
              success: false,
            });
      } else {
        res.send({ msg: "你没有权限，请联系管理员", success: false });
      }
    }
  });
});

// 错误中间组件来判断tokey错误与过期
app.use((err, req, res, next) => {
  // console.log(req.path + "测试");
  if (req.path === "/") {
    console.log(req.path + "测试");
    res.redirect("/dist");
  }
  if (err.name === "UnauthorizedError") {
    return res.send({ state: 401, message: "tokey过期", success: false });
  }
  res.send({ status: 500, message: "未知错误", success: false });
});

// 需要验证tokey接口——————————————————————————————————————————————————————————————————————————————
// 接口
app.use("/New", increaseRouter);
app.use("/Get", getRouter);
app.use("/revise", reviseRouter);
app.use("/audit", auditRouter);
app.use("/delete", DeleteRouter);

// 转化前端数据
app.all("*", function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"
  );

  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  res.header("X-Powered-By", " 3.2.1");
  req.method == "OPTIONS" ? res.send(200) : next();
});

//404页面
app.use(function (req, res, next) {
  next(createError(404));
});

// 错误中间组件
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render("error");
});
//3.启动web服务器   10.30.16.61 47.95.192.245   我启动了 http://10.30.16.61:8080
app.listen(8086, "10.30.16.76", () => {
  console.log("我启动了 http://47.95.192.245:8086");
});

module.exports = app;
